<?php

namespace App\Http\Controllers;

use App\LoginError;
use App\Project;
use App\ReviewerGroupProject;
use App\Services\AssignProjectService;
use App\Services\AwardService;
use App\Services\ManageLargeGroupService;
use App\Services\ProjectService;
use App\Services\ReviewerGroupService;
use App\Services\ReviewService;
use App\Services\WorkflowService;
use App\User;
use App\WorkflowPhase;
use Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Validator;
use Session;
use geetest\Facades\geetest;

class AdminAPIController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->awardSvc = new AwardService();
        //权限验证
        $this->middleware('check_role');
    }

    public function getAsideData()
    {
        $projectStats = DB::select('select award_id, status_id, large_group_id, count(*) as count from applications group by award_id, status_id, large_group_id');
        $certifyingOrgCount = User::where('entity_type', 'org')->where('org_certify_status', 'certifying')->count();
        $result = [
            'project_stats' => $projectStats,
            'certifying_org_count' => $certifyingOrgCount,
        ];
        return $this->json($result);
    }

    public function getAsideData1()
    {
        $projectStats = DB::select('select award_id, status_id, prof_category, count(*) as count from applications group by award_id, status_id, prof_category');
        $certifyingOrgCount = User::where('entity_type', 'org')->where('org_certify_status', 'certifying')->count();
        $result = [
            'project_stats' => $projectStats,
            'certifying_org_count' => $certifyingOrgCount,
        ];
        return $this->json($result);
    }

    public function getProjects()
    {
        $awardId = Request::get('award_id');
        $statusIds = array_filter(explode(',', Request::get('status_ids')));
        $largeGroupId = Request::get('large_group_id');
        $projects = $this->getProjectsWithApplicantInfo($awardId, $statusIds, $largeGroupId);
        $result = $projects->toArray();
        return $this->json($result);
    }

    public function getListProjectsPageData()
    {
        $awardId = Request::get('award_id');
        $statusIds = array_filter(explode(',', Request::get('status_ids')));
        $largeGroupId = Request::get('large_group_id');
        $projects = $this->getProjectsWithApplicantInfo($awardId, $statusIds, $largeGroupId)->toArray();
        $workflowSvc = new WorkflowService();
        $atPhaseFormalReview = $workflowSvc->atPhase(WorkflowService::PHASE_FORMAL_REVIEW);

        //是否可以开启"形式审查"
        //进入会评之后无法开启
        $atPhaseMeetReview = WorkflowPhase::where('phase_id', WorkflowService::PHASE_EXPERT_REVIEW)
            ->where('has_begun', 1)
            ->first();
        $result = [
            'ok'                  => true,
            'code'                => 0,
            'msg'                 => 'ok',
            'atPhaseFormalReview' => $atPhaseFormalReview,
            'atPhaseMeetReview'   => empty($atPhaseMeetReview),
            'projects'            => $projects,
        ];
        return $this->json($result);
    }

    public function endPhaseFormalReview()
    {
        $workflowSvc = new WorkflowService();
        $isOpen = Request::post('isOpen');
        if ($isOpen) {//开启形式审查
            //进入会平之后无法开启
            $res = WorkflowPhase::where('phase_id', WorkflowService::PHASE_EXPERT_REVIEW)
                ->where('has_begun', 1)
                ->first();
            if ($res) {
                return $this->json([
                    'ok' => false,
                    'msg' => '网评开始，不能执行该操作',
                ]);
            }
            $PhaseResult = $workflowSvc->beginPhase(WorkflowService::PHASE_FORMAL_REVIEW, null, false);
        } else { // 关闭形式审查
            if ($workflowSvc->notAtPhase(WorkflowService::PHASE_FORMAL_REVIEW)) {
                return $this->json([
                    'ok' => false,
                    'code' => 3,
                    'msg' => '现在不是形式审查阶段，不能执行该操作',
                ]);
            }
            $PhaseResult = $workflowSvc->endPhase(WorkflowService::PHASE_FORMAL_REVIEW, null, false);
        }

        if ($PhaseResult['ok']) {
            //关闭形式审查时开启分配评审
            if (!$isOpen) {
                WorkflowPhase::where('phase_id','C')
                    ->update([
                        'has_begun' => 1,
                        'has_ended' => 0
                    ]);
            } else {
                WorkflowPhase::where('phase_id','C')
                    ->update([
                        'has_begun' => 0,
                        'has_ended' => 0
                    ]);
            }

            $result = [
                'ok' => true,
                'code' => 0,
                'msg' => 'ok',
            ];
        } else {
            $result = [
                'ok' => false,
                'code' => 4,
                'msg' => "操作失败(code={$PhaseResult['code']}, msg={$PhaseResult['msg']})",
            ];
        }
        return $this->json($result);
    }

    public function getProjects1()
    {
        $awardId = Request::get('award_id');
        $statusIds = array_filter(explode(',', Request::get('status_ids')));
        $profCategories = array_filter(explode(',', Request::get('prof_categories')));
        $projects = $this->getProjectsWithApplicantInfo1($awardId, $statusIds, $profCategories);
        $result = $projects->toArray();
        return $this->json($result);
    }

    private function getProjectsWithApplicantInfo($awardId, $statusIds, $largeGroupId = null)
    {
        $query = DB::table('applications as A')
            ->where('A.award_id', $awardId);
        if (!empty($statusIds)) {
            $query->whereIn('status_id', $statusIds);
        }
        if ($largeGroupId !== null) {
            $query->where('large_group_id', $largeGroupId);
        }

        $query->leftJoin('award_and_expert_group_relations as B', 'A.id', '=', 'B.award_id')
            ->leftJoin('application_groups as C', 'B.award_group_id', '=', 'C.id')
            ->orderBy('A.submitted_at', 'asc')
            ->select('A.id', 'A.award_id', 'A.project_name', 'A.user_id', 'A.status_id', 'A.status_remarks', 'A.prof_category', 'B.expert_group_id', 'C.group_name', 'A.pdf_file_save_path', 'A.large_group_id');
        $projects = $query->get();

        $applicantIds = $projects->map(function ($record) {
            return $record->user_id;
        })->unique();
        $applicants = User::whereIn('id', $applicantIds)
            ->select('id', 'name', 'work_org_name', 'tel', 'email')
            ->get();

        $applicantMap = [];
        foreach ($applicants as $applicant) {
            $applicantMap[$applicant->id] = $applicant;
        }
        foreach ($projects as $project) {
            if (empty($project->nominator_ids)) {
                $project->nominator_ids = [];
            } else {
                $project->nominator_ids = explode(',', $project->nominator_ids);
            }
            $applicant = $applicantMap[$project->user_id];
            $project->applicant_name = $applicant->name;
            $project->applicant_org_name = $applicant->work_org_name;
            $project->applicant_tel = $applicant->tel;
            $project->applicant_email = $applicant->email;
            $project->status_info = $this->awardSvc->getStatusDef($project->status_id);
        }
        return $projects;
    }

    private function getProjectsWithApplicantInfo1($awardId, $statusIds, $profCategories = [])
    {
        $query = DB::table('applications as A')
            ->where('A.award_id', $awardId);
        if (!empty($statusIds)) {
            $query->whereIn('status_id', $statusIds);
        }
        if (!empty($profCategories)) {
            $query->whereIn('prof_category', $profCategories);
        }
        $query->leftJoin('award_and_expert_group_relations as B', 'A.id', '=', 'B.award_id')
            ->leftJoin('application_groups as C', 'B.award_group_id', '=', 'C.id')
            ->orderBy('A.submitted_at', 'asc')
            ->select('A.id', 'A.award_id', 'A.project_name', 'A.user_id', 'A.status_id', 'A.prof_category', 'B.expert_group_id', 'C.group_name', 'A.pdf_file_save_path');
        $projects = $query->get();
        $applicantIds = $projects->map(function ($record) {
            return $record->user_id;
        })->unique();
        $applicants = User::whereIn('id', $applicantIds)
            ->select('id', 'name', 'work_org_name', 'tel', 'email')
            ->get();
        $applicantMap = [];
        foreach ($applicants as $applicant) {
            $applicantMap[$applicant->id] = $applicant;
        }
        foreach ($projects as $project) {
            if (empty($project->nominator_ids)) {
                $project->nominator_ids = [];
            } else {
                $project->nominator_ids = explode(',', $project->nominator_ids);
            }
            $applicant = $applicantMap[$project->user_id];
            $project->applicant_name = $applicant->name;
            $project->applicant_org_name = $applicant->work_org_name;
            $project->applicant_tel = $applicant->tel;
            $project->applicant_email = $applicant->email;
            $project->status_info = $this->awardSvc->getStatusDef($project->status_id);
        }
        return $projects;
    }

    public function updateProjectStatus()
    {
        $projectId = Request::get('project_id');
        $statusId = Request::get('status_id');
        $statusRemarks = Request::get('status_remarks');
        $project = Project::find($projectId);
        $project->status_id = $statusId;
        if ($statusRemarks) {
            $project->status_remarks = $statusRemarks;
        } else {
            $project->status_remarks = '';
        }
        $project->save();
        return $this->json(['ok' => true]);
    }

    public function updateProjectAttrs()
    {
        $projectId = Request::get('project_id');
        $attrs = Request::get('attrs');
        $project = Project::find($projectId);
        $project->update($attrs);
        return $this->json(['ok' => true]);
    }

    public function projectFormalReviewPassed()
    {
        $projectId = Request::get('project_id');
        $projectSvc = new ProjectService();
        $result = $projectSvc->projectFormalReviewPassed($projectId);
        return $this->json($result);
    }

    public function createReviewer()
    {
        $data = Request::all();
        $reviewer = $data['reviewer'];
        $reviewer['id'] = null;
        $reviewer['status'] = '正常';
        $reviewer['entity_type'] = 'personal';
        $reviewer['is_applicant'] = 0;
        $reviewer['is_nominator'] = 0;
        $reviewer['is_reviewer'] = 1;
        $reviewer['is_admin'] = 0;
        $reviewer['is_tester'] = 0;

        $username = $reviewer['name'];
        $seq = 2;
        while (User::where('username', $username)->count() == 1) {
            $username = $reviewer['name'] . $seq;
            $seq++;
        }
        $reviewer['username'] = $username;

        if (is_array($reviewer['prof_fields'])) {
            $reviewer['prof_fields'] = implode(',', $reviewer['prof_fields']);
        }

        $reviewer['email'] = '';
        $reviewer['is_email_verified'] = 0;
        $reviewer['password'] = '88888888';
        $now = Carbon::now()->toDateTimeString();
        $reviewer['created_at'] = $now;
        $reviewer['updated_at'] = $now;
        $ok = false;
        $newReviewer = null;
        try {
            $newReviewer = User::create($reviewer);
            $newReviewer->attended_review = false;
            $newReviewer->prof_fields = array_filter(explode(',', $newReviewer->prof_fields));
            $ok = true;
        } catch (\Exception $e) {
            Log::error('Failed to create reviewer', ['exception' => $e]);
        }
        return $this->json(['ok' => $ok, 'reviewer' => $newReviewer]);
    }

    public function getReviewers()
    {
        // 用 DB 不用 Eloquent 才能查询 password 字段
        $reviewers = DB::table('users')
            ->where('status', '正常')
            ->where('is_reviewer', 1)
            ->orderBy('created_at', 'desc')
            ->get()
            ->toArray();
        $attendReviewReviewerIds = DB::table('reviewer_group_reviewers')->pluck('reviewer_id')->toArray();
        $attendReviewReviewerIdSet = array_flip($attendReviewReviewerIds);
        $excludedReviewers = DB::table('excluded_reviewers')->get();
        $excludedReviewerMap = [];  // reviewer_id => excluded reviewer
        foreach ($excludedReviewers as $excludedReviewer) {
            $excludedReviewerMap[$excludedReviewer->reviewer_id] = $excludedReviewer;
        }
        foreach ($reviewers as $reviewer) {
            $reviewer->attended_review = array_key_exists($reviewer->id, $attendReviewReviewerIdSet);
            $reviewer->prof_fields = array_filter(explode(',', $reviewer->prof_fields));
            $reviewerId = $reviewer->id;
            $reviewer->is_excluded = array_key_exists($reviewerId, $excludedReviewerMap);
            if ($reviewer->is_excluded) {
                $reviewer->excluded_reviewer_record_id = $excludedReviewerMap[$reviewerId]->id;
                $reviewer->excluded_reason = $excludedReviewerMap[$reviewerId]->excluded_reason;
            }
        }
        return $this->json($reviewers);
    }

    public function getManageCommissionerPageData()
    {
        $commissioners = DB::table('users')
            ->where('status', '正常')
            ->where('is_committee', 1)
            ->orderBy('created_at', 'desc')
            ->get();
        $largeGroups = DB::table('large_groups')->select('id', 'name')->orderBy('id')->get();
        $largeGroupId2Group = [];
        foreach ($largeGroups as $largeGroup) {
            $largeGroupId2Group[$largeGroup->id] = $largeGroup;
        }
        foreach ($commissioners as $commissioner) {
            $leadingLargeGroupId = $commissioner->leading_large_group_id;
            $commissioner->leading_large_group_name = $leadingLargeGroupId === null ? '' : $largeGroupId2Group[$leadingLargeGroupId]->name;
        }
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
            'commissioners' => $commissioners,
            'large_groups' => $largeGroups,
        ]);
    }

    public function createCommissioner()
    {
        $data = Request::all();
        $commissioner = $data['commissioner'];
        $commissioner['id'] = null;
        $commissioner['is_committee'] = 1;
        $commissioner['email'] = '';
        $commissioner['password'] = '12345678';
        $username = $commissioner['name'];
        $seq = 2;
        while (User::where('username', $username)->count() == 1) {
            $username = $commissioner['name'] . $seq;
            $seq++;
        }
        $commissioner['username'] = $username;
        $largeGroupId = $commissioner['leading_large_group_id'];
        if ($largeGroupId !== null) {
            if (User::where('leading_large_group_id', $largeGroupId)->count() > 0) {
                return $this->json([
                    'ok' => false,
                    'code' => 3,
                    'msg' => "该大组已被分配给其他委员，不能再分配给该委员"
                ]);
            }
        }

        $inTransaction = false;
        try {
            DB::beginTransaction();
            $inTransaction = true;
            $commissionerUser = User::create($commissioner);
            $commissionerId = $commissionerUser->id;
            DB::insert("insert ignore into `working_commissioners`(`commissioner_id`) values (?)", [$commissionerId]);
            DB::commit();
            $commissionerObject = DB::table('users')->find($commissionerId);
            if ($largeGroupId !== null) {
                $commissionerObject->leading_large_group_name = DB::table('large_groups')->where('id', $largeGroupId)->value('name');
            } else {
                $commissionerObject->leading_large_group_name = null;
            }

            return $this->json([
                'ok' => true,
                'code' => 0,
                'msg' => 'ok',
                'commissioner' => $commissionerObject,
            ]);
        } catch (\Exception $e) {
            Log::error('', ['exception' => $e]);
            if ($inTransaction) {
                try {
                    DB::rollBack();
                } catch (\Exception $e) {
                    Log::error('', ['exception' => $e]);
                }
            }
            return $this->json([
                'ok' => false,
                'code' => 2,
                'msg' => '数据库错误',
            ]);
        }
    }

    public function updateCommissioner()
    {
        $commissioner = Request::all();
        $largeGroupId = $commissioner['leading_large_group_id'];
        if ($largeGroupId !== null) {
            if (User::where('leading_large_group_id', $largeGroupId)
                    ->where('id', '!=', $commissioner['id'])
                    ->count() > 0) {
                return $this->json([
                    'ok' => false,
                    'code' => 3,
                    'msg' => "该大组已被分配给其他委员，不能再分配给该委员"
                ]);
            }
        }
        $commissioner['updated_at'] = Carbon::now()->toDateTimeString();
        $commissionerId = $commissioner['id'];
        unset($commissioner['id']);
        User::where('id', $commissionerId)->update($commissioner);
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
        ]);
    }

    public function deleteCommissioner()
    {
        $commissionerId = Request::get('id');
        $inTransaction = false;
        try {
            DB::beginTransaction();
            $inTransaction = true;
            DB::table('users')->where('id', $commissionerId)->delete();
            DB::table('working_commissioners')->where('commissioner_id', $commissionerId)->delete();
            DB::commit();
            return $this->json([
                'ok' => true,
                'code' => 0,
                'msg' => 'ok',
            ]);
        } catch (\Exception $e) {
            Log::error('', ['exception' => $e]);
            if ($inTransaction) {
                try {
                    DB::rollBack();
                } catch (\Exception $e) {
                    Log::error('', ['exception' => $e]);
                }
            }
            return $this->json([
                'ok' => false,
                'code' => 2,
                'msg' => '数据库错误',
            ]);
        }
    }

    public function createReviewerGroup()
    {
        $large_group_id = Request::get('large_group_id');
        if ($large_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param large_group_id'
            ]);
        }
        $result = (new ReviewerGroupService())->createReviewerGroup($large_group_id);
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function deleteReviewerGroup(\Illuminate\Http\Request $request)
    {
        $reviewer_group_id = Request::get('reviewer_group_id');
        if ($reviewer_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param reviewer_group_id'
            ]);
        }
        $result = (new ReviewerGroupService())->deleteReviewerGroup($reviewer_group_id);
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function updateReviewerGroupKeywords()
    {
        $reviewer_group_id = Request::get('reviewer_group_id');
        $keywords = Request::get('keywords');
        if ($reviewer_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param reviewer_group_id'
            ]);
        }
        try {
            $result = (new ReviewerGroupService())->updateReviewerGroupKeywords($reviewer_group_id, $keywords);
        } catch (\Exception $e) {
            $result = ['code' => 102, 'msg' => '构造 ReviewerGroupService 实例失败'];
        }
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function updateReviewerCanAttendReview()
    {
        $reviewer_id = Request::get('reviewer_id');
        $can_attend_review = Request::get('can_attend_review');
        if ($reviewer_id === null || $can_attend_review === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param reviewer_group_id or can_attend_review'
            ]);
        }
        try {
            $result = (new ReviewerGroupService())->updateReviewerCanAttendReview($reviewer_id, $can_attend_review);
        } catch (\Exception $e) {
            $result = ['code' => 102, 'msg' => '构造 ReviewerGroupService 实例失败'];
        }
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function autoReplaceReviewer()
    {
        $reviewer_id = Request::get('reviewer_id');
        if ($reviewer_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param reviewer_id'
            ]);
        }
        $result = (new ReviewerGroupService())->autoReplaceReviewerGroupReviewer($reviewer_id);
        return $this->json($result);
    }

    public function replaceReviewer()
    {
        $old_reviewer_id = Request::get('old_reviewer_id');
        $new_reviewer_id = Request::get('new_reviewer_id');
        $result = (new ReviewerGroupService())->replaceReviewer($old_reviewer_id, $new_reviewer_id);
        return $this->json($result);
    }

    public function selectMeetingReviewer() {
        $reviewer_id = Request::get('reviewer_id');
        $large_group_id = Request::get('large_group_id');
        $result = (new ReviewerGroupService())->selectMeetingReviewer($reviewer_id,$large_group_id);
        return $this->json($result);
    }

    public function delMeetingReviewer() {
        $reviewer_id = Request::get('reviewer_id');
        $result = (new ReviewerGroupService())->delMeetingReviewer($reviewer_id);
        return $this->json($result);
    }

    public function getMeetingReviewers(){
        $large_group_id = Request::get('large_group_id');
        $result = (new ReviewerGroupService())->getMeetingReviewers($large_group_id);
        return $this->json($result);
    }

    public function getCandidateReviewers()
    {
        $largeGroupId = Request::get('large_group_id');
        $isMeeting = Request::get('isMeeting');
        if ($isMeeting) {
            $result = (new ReviewerGroupService())->getMeetingCandidateReviewers();
        } else {
            $result = (new ReviewerGroupService())->getCandidateReviewers($largeGroupId);
        }
        return $this->json($result);
    }

    public function getReviewerGroups(\Illuminate\Http\Request $request)
    {
        $large_group_id = Request::get('large_group_id');
        if ($large_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param large_group_id'
            ]);
        }
        $result = (new ReviewerGroupService())->getReviewerGroups($large_group_id);
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function assignProjects()
    {
        $large_group_id = Request::get('large_group_id');
        if ($large_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param large_group_id'
            ]);
        }
        try {
            $result = (new AssignProjectService())->assignProjects($large_group_id);
        } catch (\Exception $e) {
            $result = ['code' => 102, 'msg' => '构造 AssignProjectService 实例失败'];
        }
        return $this->json($result);
    }

    public function cancelAssignProjects()
    {
        $large_group_id = Request::get('large_group_id');
        if ($large_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param large_group_id'
            ]);
        }
        try {
            $result = (new AssignProjectService())->cancelAssignedProjects($large_group_id);
        } catch (\Exception $e) {
            $result = ['code' => 102, 'msg' => '构造 AssignProjectService 实例失败'];
        }
        $result['ok'] = $result['code'] === 0;
        return $this->json($result);
    }

    public function submitAssignProjects()
    {
        $large_group_id = Request::get('large_group_id');
        if ($large_group_id === null) {
            return $this->json([
                'ok' => false,
                'code' => 101,
                'msg' => 'missing param large_group_id'
            ]);
        }
        try {
            $assignProjectSvc = new AssignProjectService();
        } catch (\Exception $e) {
            return $this->json([
                'ok' => false,
                'code' => 102,
                'msg' => '构造 AssignProjectService 实例失败'
            ]);
        }
        return $this->json($assignProjectSvc->submitAssignedProjects($large_group_id));
    }

    public function getPlanAwardPageData()
    {
        $large_group_id = Request::get('large_group_id');
        $phaseId = WorkflowService::PHASE_PLAN_AWARD;
        $workflowSvc = new WorkflowService();
        $hasPhasePlanAwardBegun = $workflowSvc->hasPhaseBegun($phaseId, $large_group_id);
        $atPhasePlanAward = $workflowSvc->atPhases([$phaseId], $large_group_id);
        $largeGroup = DB::table('large_groups')->find($large_group_id);
        $largeGroup->attrs = json_decode($largeGroup->attrs);
        $statusesSincePhasePlanAward = $workflowSvc->getProjectStatusesSincePhase($phaseId);
        $projects = DB::table('applications as a')
            ->where('a.large_group_id', $large_group_id)
            ->whereIn('a.status_id', $statusesSincePhasePlanAward)
            ->leftJoin('users as b', 'a.user_id', '=', 'b.id')
            ->select('a.id', 'a.project_name', 'b.name as applicant', 'a.avg_score', 'a.planned_award_level')
            ->orderBy('a.avg_score', 'desc')
            ->get();
        $projectScoreSegments = (new ProjectService())->getProjectScoreSegmentsForPlanAward($large_group_id);
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
            'hasPhasePlanAwardBegun' => $hasPhasePlanAwardBegun,
            'atPhasePlanAward' => $atPhasePlanAward,
            'largeGroup' => $largeGroup,
            'projects' => $projects,
            'project_score_segments' => $projectScoreSegments,
        ]);
    }

    public function getPrepareDefensePageData()
    {
        $large_group_id = Request::get('large_group_id');
        $phaseId = WorkflowService::PHASE_PREPARE_DEFENSE;
        $workflowSvc = new WorkflowService();
        $atPhasePrepareDefense = $workflowSvc->atPhases([$phaseId], $large_group_id);
        $projects = DB::table('candidate_defense_projects as a')
            ->leftJoin('applications as b', 'a.project_id', '=', 'b.id')
            ->leftJoin('users as c', 'b.user_id', '=', 'c.id')
            ->where('a.large_group_id', $large_group_id)
            ->select('a.project_id', 'a.is_selected',
                'b.project_name', 'b.avg_score',
                'c.name as applicant_name', 'c.tel as applicant_tel', 'c.email as applicant_email', 'c.work_org_name as applicant_work_org_name')
            ->orderBy('b.avg_score', 'desc')
            ->get()->toArray();
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
            'atPhasePrepareDefense' => $atPhasePrepareDefense,
            'projects' => $projects,
        ]);
    }

    public function updateCandidateDefenseProjectsStatus() {
        $items = Request::get('items');
        $selected2projectIds = [[], []];
        foreach ($items as $item) {
            $selected2projectIds[$item['is_selected']][] = $item['project_id'];
        }
        $inTransaction = false;
        try {
            DB::beginTransaction();
            $inTransaction = true;
            foreach ($selected2projectIds as $selected => $projectIds) {
                if (!empty($projectIds)) {
                    DB::table('candidate_defense_projects')->whereIn('project_id', $projectIds)->update(['is_selected' => $selected]);
                }
            }
            DB::commit();
            return $this->json([
                'ok' => true,
                'code' => 0,
                'msg' => 'ok',
            ]);
        } catch (\Exception $e) {
            Log::error('', ['exception' => $e]);
            if ($inTransaction) {
                try {
                    DB::rollBack();
                } catch (\Exception $e) {
                    Log::error('', ['exception' => $e]);
                }
            }
            return $this->json([
                'ok' => false,
                'code' => 2,
                'msg' => '数据库错误',
            ]);
        }
    }

    public function autoSetAwardLevel()
    {
        $data = Request::all();
        $manageLargeGroupSvc = new ManageLargeGroupService();
        $result = $manageLargeGroupSvc->adminAutoSetAwardLevel($data['large_group_id'], $data['awards']);
        return $this->json($result);
    }

    public function updatePlannedAwardLevel()
    {
        $data = Request::all();
        $manageLargeGroupSvc = new ManageLargeGroupService();
        $result = $manageLargeGroupSvc->adminUpdatePlannedAwardLevel($data['project_id'], $data['planned_award_level']);
        return $this->json($result);
    }

    public function submitPlanAwardResult()
    {
        $manageLargeGroupSvc = new ManageLargeGroupService();
        $result = $manageLargeGroupSvc->adminSubmitPlanAwardResult(Request::get('large_group_id'));
        return $this->json($result);
    }

    public function submitPrepareDefenseResult() {
        $manageLargeGroupSvc = new ManageLargeGroupService();
        $result = $manageLargeGroupSvc->adminSubmitPrepareDefenseResult(Request::get('large_group_id'));
        return $this->json($result);
    }

    public function getReviewerProgress()
    {
        $largeGroupId = Request::get('large_group_id');
        $reviewerProjectStats = (new ReviewService())->getReviewerProjectStats($largeGroupId);
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
            'reviewerProgress' => $reviewerProjectStats,
        ]);
    }

    public function getProjectScoreSegmentsAtExpertReview()
    {
        $largeGroupId = Request::get('large_group_id');
        $projectScoreSegments = (new ProjectService())->getProjectScoreSegmentsAtExpertReview($largeGroupId);
        return $this->json([
            'ok' => true,
            'code' => 0,
            'msg' => 'ok',
            'project_score_segments' => $projectScoreSegments,
        ]);
    }

    public function getFeedbacks()
    {
        $feedbacks = DB::table('feedbacks')
            ->orderBy('created_at', 'desc')
            ->get()->toArray();
        $id2users = [];
        if (!empty($feedbacks)) {
            $submitter_ids = array_map(function ($feedback) {
                return $feedback->submitter_id;
            }, $feedbacks);
            $submitter_ids = array_unique($submitter_ids);
            $users = DB::table('users')
                ->select('id', 'name', 'prof_title', 'tel', 'work_org_name')
                ->whereIn('id', $submitter_ids)
                ->get();
            foreach ($users as $user) {
                $id2users[$user->id] = $user;
            }
        }
        foreach ($feedbacks as $feedback) {
            $submitter_id = $feedback->submitter_id;
            $feedback->submitter = isset($id2users[$submitter_id]) ? $id2users[$submitter_id] : (object)[
                'id' => $submitter_id,
                'name' => null,
                'prof_title' => null,
                'tel' => null,
                'work_org_name' => null,
            ];
        }
        return $this->json($feedbacks);
    }


    /**
     * 获取登陆错误限制列表
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/8 5:44 下午
     * @流程:
     */
    public function getLoginError() {
        $list = LoginError::where('error_num','>=',LoginError::LOGIN_ERROR_NUM_LIMIT)->get()->toArray();
        return $this->json([
            'ok'    => true,
            'list'  => $list
        ]);
    }

    /**
     * 解除限制状态
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/8 5:45 下午
     * @流程:
     */
    public function clearErrorNum() {
        $data = Request::all();
        $res = LoginError::IpUnfreeze($data['ip']);
        if ($res === true) {
            return $this->json([
                'ok'   => true,
                'msg'  => '操作完成'
            ]);
        } else {
            return $this->json([
                'ok'   => false,
                'msg'  => '操作失败：'.$res
            ]);
        }
    }


    /**
     * 获取项目评分信息
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/11 9:11 下午
     * @流程:
     */
    public function getProjectData(){
        $largeGroupId = Request::post('large_group_id');
        $result = (new ProjectService())->adminGetExpertReviewProjects($largeGroupId);
        if (!$result['ok']) {
            return $this->json($result);
        }

        $result2 = (new ManageLargeGroupService())->getLargeGroupById($largeGroupId);
        if (!$result2['ok']) {
            return $this->json($result2);
        }
        $result['large_group'] = $result2['large_group'];
        return $this->json($result);
    }

    /**
     * 导出excel
     * @author: lxy
     * @time: 2020/6/15 2:30 下午
     * @流程:
     */
    public function excelExport() {
        $result = (new \App\Services\ExcelExportService(Request::post()))->Export();
        return $this->json($result);
    }

    /**
     * 获取会评列表
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/17 8:25 下午
     * @流程:
     */
    public function getMeetingProject(){
        $largeGroupId = Request::post('large_group_id');
        $result = (new ProjectService())->leaderGetMeetingReviewProjects($largeGroupId);
        return $this->json($result);
    }

    /**
     * 开启/结束 申报阶段
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/17 8:29 下午
     * @流程:
     */
    public function updateDeclarePhase(){
        $applyPhase = WorkflowPhase::where('phase_id', WorkflowService::PHASE_APPLY)->first();
        if ($applyPhase->has_ended == 1
            || $applyPhase->has_begun == 0) {
            $applyPhase->has_begun = 1;
            $applyPhase->has_ended = 0;
            $msg = '已开启申报阶段';
        } else {
            $applyPhase->has_begun = 1;
            $applyPhase->has_ended = 1;
            $msg = '已关闭申报阶段';
        }
        $res = $applyPhase->save();
        if ($res) {
            $result = [
                'ok' => true,
                'msg' => $msg
            ];
        } else {
            $result = [
                'ok' => false,
                'msg' => '操作失败，请重试'
            ];
        }
        return $this->json($result);
    }

    /**
     * 获取申报阶段状态
     * @return \Illuminate\Http\JsonResponse
     * @author: lxy
     * @time: 2020/6/17 8:42 下午
     * @流程:
     */
    public function getDeclarePhase(){
        $workflowService = new WorkflowService();
        $status = $workflowService->atPhase(WorkflowService::PHASE_APPLY);
        $result = [
            'ok' => true,
            'status' => $status
        ];
        return $this->json($result);
    }

}